package com.oig.sys.base.controller;


import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.oig.common.exception.BadRequestException;
import com.oig.common.module.SysRequest;
import com.oig.common.module.SysResponse;
import com.oig.common.validator.GroupAdd;
import com.oig.common.validator.GroupEdit;
import com.oig.sys.base.app.IAppPortService;
import com.oig.sys.base.dto.PortDto;
import com.oig.sys.base.service.ITbCountryService;
import com.oig.sys.base.service.ITbPortService;
import com.oig.sys.base.vo.CountryVo;
import com.oig.sys.base.vo.PortVo;
import com.oig.sys.log.annotation.SysLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Tag(name = "港口管理")
@RestController
@RequestMapping("/port")
@Slf4j
@RequiredArgsConstructor
public class TbPortController {

    private final IAppPortService appPortService;
    private final ITbPortService portService;
    private final ITbCountryService countryService;


    @PreAuthorize("@pms.hasPermission('/port/addPort')")
    @SysLog(value="添加港口",apiUrl="/port/addPort")
    @Operation(summary = "添加港口")
    @PostMapping(value = "/addPort")
    public PortVo addPort(@RequestBody @Validated(GroupAdd.class) PortDto portDto){
        log.info("add Port {}",portDto);
        return this.appPortService.addPort(portDto);
    }

    @PreAuthorize("@pms.hasPermission('/port/updatePort')")
    @SysLog(value="修改港口",apiUrl="/port/updatePort")
    @Operation(summary = "修改港口")
    @PostMapping(value = "/updatePort")
    public PortVo updatePort(@RequestBody @Validated(GroupEdit.class) PortDto portDto){
        log.info("update Port {}",portDto);
        return this.appPortService.updatePort(portDto);
    }

    @PreAuthorize("@pms.hasPermission('/port/cancelPort')")
    @SysLog(value="逻辑删除港口",apiUrl="/port/cancelPort")
    @Operation(summary = "逻辑删除港口")
    @PostMapping(value = "/cancelPort/{code}")
    public SysResponse<String> cancelPort(@PathVariable("code") String code){
        log.info("cancel Port code={}", code) ;
        this.appPortService.cancelPort(code);
        return SysResponse.ok(code,"逻辑删除港口成功");
    }


    @Operation(summary = "查询备选港口,输入选择框时使用，返回前N条记录")
    @PostMapping(value = "/findPort")
    public List<PortVo> findPort(@RequestBody SysRequest<PortDto> portRequest){
        log.info("find Port {}", portRequest) ;
        return this.portService.findPort(portRequest) ;
    }


    /**
     * 初始化数据用的接口
     */
    @PreAuthorize("@pms.hasPermission('/port/importPort')")
    @SysLog(value="批量导入港口",apiUrl="/port/importPort")
    @PostMapping("/importPort")
    @Operation(summary = "批量导入港口,json 文件导入")
    public SysResponse<String> importPort(@RequestPart("jsonFile") MultipartFile jsonFile){
        if (jsonFile == null || jsonFile.getSize() == 0 || StrUtil.isBlank(jsonFile.getOriginalFilename())) {
            throw new BadRequestException("空文件..");
        }
        Map<String,CountryVo> countryVoMap = new HashMap<>();
        try{
            EasyExcel.read(jsonFile.getInputStream(), new PageReadListener<Map<Integer, String>>(dataList -> {
                String isoCode ;
                for (Map<Integer, String> dataMap : dataList){
                    log.debug("excel data map:{}",dataMap);
                    PortVo portVo = this.portService.getByName(dataMap.get(0));
                    if (portVo!=null){
                        log.warn("已存在港口：{}", portVo);
                        continue;
                    }
                    PortDto portDto = new PortDto();
                    portDto.setCode(dataMap.get(1));
                    portDto.setName(dataMap.get(0));
                    portDto.setEnName(dataMap.get(2));
                    if ("142".equals(dataMap.get(3))){
                        isoCode = "CHN" ;
                    } else {
                        isoCode = portDto.getCode().substring(0,3) ;
                    }
                    log.info("isoCode:{}", isoCode);
                    CountryVo countryVo = countryVoMap.get(isoCode) ;
                    if (countryVo==null){
                        countryVo = this.countryService.getCountryByIsoCode(isoCode) ;
                        if (countryVo!=null) {
                            countryVoMap.put(isoCode, countryVo);
                        }
                    }
                    if (countryVo!=null){
                        portDto.setCountryCode(countryVo.getCode());
                        portDto.setCountryName(countryVo.getName());
                    }
                    this.portService.addPort(portDto);
                }
            })).headRowNumber(2).sheet().doRead();
        } catch (Exception e){
            log.error("file upload error", e);
            return SysResponse.failed("导入港口失败");
        }
        return SysResponse.ok(jsonFile.getOriginalFilename(),"导入港口成功");
    }


    @Operation(summary = "根据名称获取港口")
    @PostMapping(value = "/getByName")
    public PortVo getByName(@RequestParam("name") String name){
        log.info("get port By Name：{}",name);
        return this.portService.getByName(name);
    }

    @Operation(summary = "根据原code获取港口")
    @PostMapping(value = "/getByOldCode")
    public PortVo getByOldCode(@RequestParam("oldCode") String oldCode){
        log.info("get port by old code：{}",oldCode);
        return this.portService.getByOldCode(oldCode);
    }

    @Operation(summary = "根据code获取港口")
    @PostMapping(value = "/getByCode")
    public PortVo getByCode(@RequestParam("code") String code){
        log.info("get port by code：{}",code);
        return this.portService.getByCode(code);
    }


}
